{-----------------------------------------------------------------

  (c) 2008-2009 Markus Dittrich 
 
  This program is free software; you can redistribute it 
  and/or modify it under the terms of the GNU General Public 
  License Version 3 as published by the Free Software Foundation. 
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License Version 3 for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 59 Temple Place - Suite 330, 
  Boston, MA 02111-1307, USA.

--------------------------------------------------------------------}

{-|
   this module parses the command line options for the 
   word count utility
-}
module Parsers.CommandLine ( defaultOptions
                           , getArgs
                           , options
                           , Options(..)
                           , Query(..)
                           , show_usage
                           , module System.Console.GetOpt 
                           ) where


-- imports
import Prelude
import System(exitWith, ExitCode(..))
import System.Console.GetOpt(ArgDescr(..), ArgOrder(..), getOpt, 
  OptDescr(..), usageInfo)
import System.Environment(getArgs)

-- local imports
import Helpers.Common(show_version)


-- | data structure for keeping track of command
-- line requests. If only a subset of a package's content
-- is requested we assume that
--
--    *binaries are in \/usr\/bin, \/usr\/sbin
--     \/bin\/, \/sbin,
--
--    *libraries are in \/lib\/, \/lib64, 
--     \/usr\/lib, \/usr\/lib64
--
--    *docs are in \/usr\/share\/doc
--
--    *for the remainder we provide filters for \/etc,
--     \/usr\/include, and all of \/usr\/share
--
data Query = BinContents 
           | CheckAll
           | Contents 
           | DependAll
           | DependUsed 
           | DocContents
           | EtcContents 
           | IncludeContents 
           | LibContents 
           | None 
           | Owner 
           | SearchShort
           | SearchDetailed
           | ShareContents 
           | UseAll
           | UseUsed
           | Version
  deriving(Eq)



-- | data structure for keeping track of selected command line options
data Options = Options {
  theQuery :: Query,
  queryOpt :: String
} 



-- | default selections
defaultOptions :: Options
defaultOptions = Options {
  theQuery = None,
  queryOpt = ""
}



-- | available command line flags
options :: [OptDescr (Options -> IO Options)]
options = [ 
  Option ['c'] ["check-all"] (NoArg check_all)
    "check all packages for consistency",
  Option ['d'] ["find-depends-used"] (NoArg find_depends)
    "search for all packages depending on PACKAGE",
  Option ['D'] ["find-depends-all"] (NoArg find_depends_used)
    "search for all packages depending on PACKAGE (ignore \
    \packages not request by a USE flag)",
  Option ['f'] ["show-all-content"] (NoArg find_all_contents)
    "show all files installed by PACKAGE (abort in case of \ 
     \multiple matches)", 
  Option ['F'] ["show-restricted-content"] 
    (ReqArg find_restricted_contents "SPEC") 
    "like show-all-content but restrict output according to SPEC",
  Option ['o'] ["owns-file"] (NoArg find_owner) 
    "find the package which owns file at FILEPATH", 
  Option ['s'] ["find-package-short"] (NoArg find_package_short) 
    "search for package(s) matching pattern (short and fast)",
  Option ['S'] ["find-package-detailed"] 
    (NoArg find_package_detailed) 
    "search for package(s) matching pattern and provide detailed \
    \package information",
  Option ['U'] ["find-use-all"] (NoArg find_use_all) 
    "find all packages that have useflag USE", 
  Option ['u'] ["find-use-used"] (NoArg find_use_used) 
    "find all packages that have useflag USE", 
  Option ['h'] ["help"] (NoArg show_usage) 
    "show usage information",
  Option ['v'] ["version-info"] (NoArg version_info) 
    "show version information"]



-- | check all installed packages for consistency 
-- (all files present, size, md5sum)
check_all :: Options -> IO Options
check_all opt =
  return opt { theQuery = CheckAll }



-- | initiate query for name of depend package
find_depends :: Options -> IO Options
find_depends opt =
  return opt { theQuery = DependUsed }



-- | initiate query for name of used depend package
find_depends_used :: Options -> IO Options
find_depends_used opt =
  return opt { theQuery = DependAll }



-- | initiate query to show all files belonging to a package
find_all_contents :: Options -> IO Options
find_all_contents opt =
  return opt { theQuery = Contents }



-- | initiate query to show a specified subset of files 
-- belonging to a package 
find_restricted_contents :: String -> Options -> IO Options
find_restricted_contents arg opt =

  case arg of
    "b" -> return opt { theQuery = BinContents }
    "d" -> return opt { theQuery = DocContents }
    "e" -> return opt { theQuery = EtcContents }
    "i" -> return opt { theQuery = IncludeContents }
    "l" -> return opt { theQuery = LibContents }
    "s" -> return opt { theQuery = ShareContents }
    _   -> return opt { theQuery = Contents }



-- | initiate query for the package owning a file
find_owner :: Options -> IO Options
find_owner opt = 
  return opt { theQuery = Owner }



-- | initiate a quick search (displays only package
-- name but is fast)
find_package_short :: Options -> IO Options
find_package_short opt = 
  return opt { theQuery = SearchShort }



-- | initiate a detailed search (displays detailed
-- package information)
find_package_detailed :: Options -> IO Options
find_package_detailed opt = 
  return opt { theQuery = SearchDetailed }



-- | initiate a query for all packages that have
-- a particular useflag 
find_use_all :: Options -> IO Options
find_use_all opt = 
  return opt { theQuery = UseAll }



-- | initiate a query for all packages that have
-- a particular useflag and were also emerged
-- with it present
find_use_used :: Options -> IO Options
find_use_used opt = 
  return opt { theQuery = UseUsed }



-- | initiate query to show usage info
show_usage :: Options -> IO Options
show_usage _ = 
  (putStrLn $ usageInfo "Usage: hark OPTIONS PATTERN\n\n" options)
  >> exitWith ExitSuccess



-- | initiate query to show version info
version_info :: Options -> IO Options
version_info _ = show_version
                 >> exitWith ExitSuccess
